/*------------------------------------------------------------
 * Function excentricLabel
 *-----------------------------------------------------------*/
function excentricLabel(e){
  var currentZoomLevel = e.tile.element;
  var $parent = $('svg');


  d3.select('svg.map')
    .on("mousemove", function() {
    //.on("click", function() {
      $('g.focus-area-container').remove();
      $('.icon_cluster').stop(true,true).fadeIn();
      apply(event);
    });

  function apply(e){
    //config the focus view
    var focusArea = {
      strokeColor: "black",
      strokeWidth:2,
      r:40,
      dot:{r:2,color:"red"},
      labelFontSize: 11,
      labelBackground:'#eee',
      lineWidth:2,
      lineColor:"black",
      labelOffset: 20,
      maxNum: 10,
      iconLabelHeight:16,
      iconLabelWidth:16,
      iconCollapsedHeight:20,
      iconCollapsedWidth:13,
      iconCollapsedUrl:'img/icon.png',
      textCollapseUrl:'img/text_black.png',
      summaryHeight: 20,
      summaryWidth: 40
    }

    var $currentZoomLevel = $(currentZoomLevel);
    var container = d3.select(currentZoomLevel)
      .append('g')
      .attr('class','focus-area-container');
    var mp = mousePosition(e,$currentZoomLevel);
    var textTotalCount = 0;
    var iconTotalCount = 0;
    var elementsInFocusArea = []; 
    process();

    //get the position relative to the current zoom level.
    function mousePosition(e,$parent){
      var p = {};
      p.x = e.pageX - getX($parent) - getX($('.layer2'));
      p.y = e.pageY - getY($parent) - getY($('.layer2'));
      return p;
    }

    function process(){
      findFocusedElements();
      //console.log(elementsInFocusArea.length);
      if(elementsInFocusArea.length > 0){
        drawCircle();
        sortWithY(elementsInFocusArea);
        hideIconCluster();
        var leftNum = 0;
        var rightNum = 0;
        var textCount = 0;
        var iconCount = 0;
        for(i=0;i<elementsInFocusArea.length;i++){
          var e = elementsInFocusArea[i];
          if(leftNum<focusArea.maxNum/2 && e.x<=mp.x){
            if(e.type == 'text'){
              textLabeling(e,leftNum,'left');
              textCount += 1;
            }else{
              iconLabeling(e,leftNum,'left');
              iconCount += 1;
            }
            leftNum += 1;
          }
          else if(rightNum<focusArea.maxNum/2 && e.x>mp.x){
            if(e.type == 'text'){
              textLabeling(e,rightNum,'right');
              textCount += 1;
            }else{
              iconLabeling(e,rightNum,'right');
              iconCount += 1;  
            }
            rightNum += 1;
          }
        }
        tsp = textSummaryPosition(leftNum);
        isp = iconSummaryPosition(rightNum);
        addTextSummaryLabel(tsp.x,tsp.y,textTotalCount - textCount);
        addIconSummaryLabel(isp.x,isp.y,iconTotalCount - iconCount);
      }
    }

    function findFocusedDots(){
      $('g.text-dot-container text').each(function(){
        if(isInFocusArea($(this),'text')) elementsInFocusArea.push(new FocusedElement($(this),'text'));
      });
    }

    //Return true if the center of the element is in the focus area
    function isInFocusArea($element,type){
      var p = getCenterPosition($element,type);
      return distance(p.x,p.y,mp.x,mp.y) < focusArea.r;
    }

    function getCenterPosition($element,type){
      var centerPosition = {};
      switch (type){
        case "text":
        case "cluster":
        case "image":
          centerPosition.x = getX($element);
          centerPosition.y = getY($element);
          break;
        case 'g':
          centerPosition.x = getX($element) + focusArea.summaryWidth / 2;
          centerPosition.y = getY($element) + focusArea.summaryHeight / 2;
          break;
        case 'circle':
          if($element.length != null){
            centerPosition.x = parseInt($element.attr('cx'));
            centerPosition.y = parseInt($element.attr('cy'));
          }else{
            centerPosition.x = parseInt($element.getAttribute('cx'));
            centerPosition.y = parseInt($element.getAttribute('cy'));
          }
          break;
      } 
      return centerPosition;
    }

    function getImageSize($image){
      var size = {};
      size.h = parseFloat($image.attr('height'));
      size.w = parseFloat($image.attr('width'));
      return size;
    }

    function distance(x1,y1,x2,y2){
      return Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
    }

    function drawCircle(){
      container.append('circle')
        .attr('id','focusArea')
        .style('fill','none')
        .attr('stroke',focusArea.strokeColor)
        .attr('stroke-width',focusArea.strokeWidth)
        .attr('cx',mp.x)
        .attr('cy',mp.y)
        .attr('r',0)
        .transition()
        .attr('r',focusArea.r);
    }

    function sortWithY(elements){
      function swap(){
        var temp = elements[i];
        elements[i] = elements[j];
        elements[j] = temp;
      }
      for(i = 0;i < elements.length;i++){
        for(j = i + 1;j < elements.length;j++){
          left = elements[i].y;
          right = elements[j].y;;
          if(left > right) swap();
        }
      }
    }

    function hideIconCluster(){
      $('.icon_cluster').each(function(){
        if(isInFocusArea($(this),'cluster') && $(this).children().size() > 1){
          $(this).stop(true,true).fadeOut();
        }
      })
    }

    function collapseIconOrTextEL($element,type){
      $element.css('display','none');
      container.append('circle')
        .attr('class',function(){
          return "'" + type + "-dot";
        })
        .attr('cx',getCenterPosition($element,type).x)
        .attr('cy',getCenterPosition($element,type).y)
        .attr('r',focusArea.dot.r)
        .style('fill',focusArea.dot.color);
    }

    function textLabeling(element,i,position){
      var num = focusArea.maxNum / 2;
      var x = (position == 'left' ? mp.x - focusArea.r - focusArea.labelOffset : mp.x + focusArea.r + focusArea.labelOffset);
      var y = mp.y - focusArea.r + focusArea.r * i * 2 / (num - 1);
      attachTextLabel(element,x,y,position);
      drawLine(element.x,element.y,x,y);
    }

    function attachTextLabel(element,x,y,position){
      var anchorPosition = (position == 'left' ? 'end' : 'start');
      var text = container.append('text');
      text.text(element.text)
          .attr('font-size',focusArea.labelFontSize)
          .attr('alignment-baseline','middle')
          .attr('text-anchor',anchorPosition)
          .attr('class',function(){return 'text-label-content text-label ' + position})
          .style('fill',element.color)
          .attr('transform',function(){
            return "translate(" + element.x + "," + element.y + ")"
          })
          .transition()
          .attr('transform',function(){
            return "translate(" + x + "," + y + ")";
          })
          .each('end',function(){
            addTextBackground($(this));
          });
    }

    function addTextBackground($text){
      var position = $text.attr('class').replace('text-label-content text-label ','');
      addBackground($text,'text',position)
    }

    function addBackground($element,type,position){
      var element = new FocusedElement($element,type);
      var className = $element.attr('class').match(/[^\s]+/);
      var before = '.' + className; 
      d3.select('.focus-area-container').insert('rect',before)
        .attr('class','label-background')
        .attr('x',function(){
          if(type == 'g') return element.x - 20;
          return (position == 'left' ? element.x - element.w : element.x);
        })
        .attr('y',function(){
          return element.y - element.h / 2;
        })
        .attr('width',1.1*element.w)
        .attr('height',element.h)
        .attr('transform','translate(-2,-2)')
        .style('stroke',element.color)
        .style('stroke-width',focusArea.strokeWidth)
        .style('fill',focusArea.labelBackground)
        .style('opacity',0)
        .transition()
        .style('opacity',1);;  
    }

    function drawLine(x1,y1,x2,y2){
      container.append('line')
          .style('stroke',focusArea.lineColor)
          .style('stroke-width',focusArea.lineWidth)
          .attr('class','text-label-line text-label')
          .attr('x1',x1)
          .attr('x2',x1)
          .attr('y1',y1)
          .attr('y2',y1)
          .transition()
          .attr('x1',x1)
          .attr('x2',x2)
          .attr('y1',y1)
          .attr('y2',y2);        
    }
    
    function iconLabeling(element,i,position){
      collapseIconCluster(element);
      var num = focusArea.maxNum / 2;
      var x = (position == 'left' ? mp.x - focusArea.r - focusArea.labelOffset : mp.x + focusArea.r + focusArea.labelOffset);
      var y = mp.y - focusArea.r + focusArea.r * i * 2 / (num - 1);
      var dx = (position == 'left' ? - focusArea.iconLabelWidth : 0);
      var dy = - focusArea.iconLabelHeight / 2
      attachIconLabel(element,x + dx,y + dy);
      drawLine(element.x,element.y,x,y);
    }

    function collapseIconCluster(element){
      container.append('image')
        .attr('xlink:href',focusArea.iconCollapsedUrl)
        .attr('class', 'collapsed-icon')
        .attr('height',0)
        .attr('width',focusArea.iconCollapsedWidth)
        .attr('transform',function(){
          var x = element.x - focusArea.iconCollapsedWidth / 2;
          var y = element.y - focusArea.iconCollapsedHeight / 2;
          return 'translate(' + x + ',' + y + ')';
        })
        .transition()
        .attr('height',focusArea.iconCollapsedHeight);
    }

    function attachIconLabel(element,x,y){
      container.append('image')
        .attr('xlink:href',element.url)
        .attr('transform',function(){
          return "translate(" + element.x + "," + element.y + ")";
        })
        .attr('class','icon-label')
        .attr('height',focusArea.iconLabelHeight)
        .attr('width',focusArea.iconLabelWidth)
        .transition()
        .attr('transform',function(){
          return "translate(" + x + "," + y + ")";
        }); 
    }

    function findFocusedElements(){
      findFocusedTexts();
      findFocusedIcons();
    }
    
    function FocusedElement($element,type){
      this.content = $element;
      this.type = type;
      this.x = getCenterPosition($element,type).x;
      this.y = getCenterPosition($element,type).y;
      if(type == 'text'){
        this.text = $element.attr('title');
        this.h = $element.height();
        this.w = $element.width();
        this.color = $element.css('fill');
      }else if(type == 'image'){
        this.url = $element.attr('href');
      }else if(type == 'g'){
        this.h = focusArea.summaryHeight;
        this.w = focusArea.summaryWidth;
        this.color = 'black';
      }
    }

    //only find collapsed text
    function findFocusedTexts(){
      $('.text-dot-container text').each(function(){
        if(isInFocusArea($(this),'text')){
          elementsInFocusArea.push(new FocusedElement($(this),'text'));  
          textTotalCount += 1;
        }  
      })
    }

    function findFocusedIcons(){
      $('.icon_cluster').each(function(){
        if(isInFocusArea($(this),'cluster')){
          if($(this).children().size() > 1){
            var iconCluster = new IconCluster($(this));
            iconCluster.elements.forEach(function(value,index){
              elementsInFocusArea.push(new FocusedElement(value,'image'));
            })
          }
        }   
      })
    }

    function IconCluster($cluster){
      var className = $cluster.attr('class').replace('icon_cluster ','');
      var arr = [];
      $('.point_icon.' + className).each(function(){
        if(isInFocusArea($(this),'image')) arr.push($(this));
      });
      this.elements = arr;
      //this.elements = $('.point_icon.' + className);
    }

    function addTextSummaryLabel(x,y,num){
      if(num > 0){
        var g = d3.select('.focus-area-container').append('g').attr('class','text-summary-label');
        g.attr('transform',function(){
              return 'translate(' + x + ',' + y + ')';
            })
        addSummaryContent(g);
        addBackground($('.text-summary-label'),'g','left');
      }
      function addSummaryContent(g){
        g.append('text')
          .text(function(){return '+' + num})
          .style('font-size',focusArea.labelFontSize)
          .attr('alignment-baseline','middle')
          .attr('text-anchor','middle')
          .attr('transform','translate(10,11)')
          .style('opacity',0)
          .transition()
          .style('opacity',1);
        g.append('image')
            .attr('xlink:href',focusArea.textCollapseUrl)
            .attr('height',focusArea.iconLabelHeight)
            .attr('width',focusArea.iconLabelWidth)
            .attr('transform','translate(20,0)')
            .style('opacity',0)
            .transition()
            .style('opacity',1);
      } 
    }

    function addIconSummaryLabel(x,y,num){
      if(num > 0){
        var g = d3.select('.focus-area-container').append('g')
            .attr('class','icon-summary-label')
            .attr('transform',function(){
              return 'translate(' + x + ',' + y + ')';
            });
        g.append('text')
            .text(function(){return '+' + num})
            .style('font-size',focusArea.labelFontSize)
            .attr('alignment-baseline','middle')
            .attr('text-anchor','middle')
            .attr('transform','translate(10,11)')
            .style('opacity',0)
            .transition()
            .style('opacity',1);
        g.append('image')
            .attr('xlink:href',focusArea.iconCollapsedUrl)
            .attr('height',focusArea.iconLabelHeight)
            .attr('width',focusArea.iconLabelWidth)
            .attr('transform','translate(20,0)')
            .style('opacity',0)
            .transition()
            .style('opacity',1);;
        addBackground($('.icon-summary-label'),'g','right');
      }
    }

    function textSummaryPosition(leftNum){
      var p = {};
      p.x = mp.x - focusArea.r - focusArea.labelOffset - focusArea.summaryWidth;
      p.y  = mp.y - focusArea.r + focusArea.r * ( leftNum + 1 ) * 2 / (focusArea.maxNum / 2 - 1) - focusArea.summaryHeight;
      return p;
    }

    function iconSummaryPosition(rightNum){
      var p = {};
      p.x = mp.x + focusArea.r + focusArea.labelOffset;
      p.y  = mp.y - focusArea.r + focusArea.r * ( rightNum + 1 ) * 2 / (focusArea.maxNum / 2 - 1) - focusArea.summaryHeight;
      return p;
    }
  }
}









